/**
 * 
 */
package ch.gje.playios.server.handler;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import ch.gje.playios.server.HTTPConnection;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

/**
 * Handles HTTP requests
 * 
 * @author jannis <jannis@gje.ch>
 */
public class HTTPHandler extends RequestHandler {

    /**
     * The request headers
     */
    private Map<String, String> headers;
    /**
     * The requested resource
     */
    private String resource;

    /**
     * Constructor
     *
     * @param connection
     *            the HTTP connection
     */
    public HTTPHandler(HTTPConnection connection) {
        super(connection);
        headers = connection.getHeaders();
        resource = headers.get(HTTPConnection.REQUEST_RESOURCE);
        if (resource.endsWith("/")) {
            resource += "index.html";
        }
        // /index.html is internal /index.computer.html or /index.ios.html
        if (resource.equals("/index.html")) {
            String userAgent = headers.get("User-Agent");
            System.out.println(userAgent);
            if (userAgent != null && userAgent.contains(" Mobile/")
                    && userAgent.contains(" AppleWebKit/")) {
                resource = "/index.ios.html";
            } else {
                resource = "/index.computer.html";
            }
        }
        resource = resource.split("\\?")[0]; // Strip GET parameters because
        // they aren't evaluated
        handle();
    }

    /*
     * (non-Javadoc)
     *
     * @see server.QueryHandler#handleQuery(java.lang.String, java.lang.String)
     */
    @Override
    public void handleQuery() throws IOException {
        if (resource.contains("/../")) {
            new ForbiddenHandler(connection,
                    "Paths containing /../ are not allowed.");
        } else {
            InputStream file = getClass().getResourceAsStream(
                    "/htdocs" + resource);
            if (file != null) {
                setResponseStatus(200, "OK");
                if (resource.endsWith(".html")) {
                    setHeader("Content-Type", "text/html; charset=UTF-8");
                } else if (resource.endsWith(".css")) {
                    setHeader("Content-Type", "text/css");
                } else if (resource.endsWith(".js")) {
                    setHeader("Content-Type", "text/javascript");
                } else if (resource.endsWith(".png")) {
                    setHeader("Content-Type", "image/png");
                } else if (resource.endsWith(".ico")) {
                    setHeader("Content-Type", "image/x-icon");
                }
                sendHeaders();

                BufferedInputStream fileStream = new BufferedInputStream(file);
                byte[] bytes = new byte[100];
                try {
                    int read;
                    while ((read = fileStream.read(bytes)) != -1) {
                        if(read < 100) {
                            byte[] shortBytes = new byte[read];
                            System.arraycopy(bytes, 0, shortBytes, 0, read);
                            bytes = shortBytes;
                        }
                        connection.send(bytes);
                        bytes = new byte[100]; // clear
                    }
                } finally {
                    fileStream.close();
                    connection.close();
                }
            } else {
                new NotFoundHandler(connection);
            }
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see server.RequestHandler#handleServerError()
     */
    @Override
    protected void handleServerError() {
        try {
            if (resource.endsWith(".html")) {
                connection.send("\r\n<br>\r\n<br>\r\n<br>\r\n500: Internal Server Error.");
            } else if (resource.endsWith(".js") || resource.endsWith(".css")) {
                connection.send("\r\n\r\n\r\n/* 500: Internal Server Error. */");
            }
        } catch (Exception e) {
            // no good
        }
    }
}
